﻿using System;
using System.Data;
using CoreComponents.DataAccess;
using Crowler.Model.CoreComponents.DataAccess;
using Crowler.TestBase;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NHibernate;

namespace Crowler.CoreComponents.Test
{
    [TestClass]
    public class UnitOfWorkImplementorShould:TestBaseClass
    {
        private Mock<IUnitOfWorkFactory> _unitOfWorkFactoryMock;
        private Mock<ISession> _sessionMock;
        private UnitOfWork _unitOfWork;
        private Mock<ITransaction> _transactionMock;


        public override void TestCleanup()
        {
        }

        public override void TestInitialize()
        {
            _unitOfWorkFactoryMock = new Mock<IUnitOfWorkFactory>();
            _sessionMock = new Mock<ISession>();
            _transactionMock = new Mock<ITransaction>();
            _sessionMock.Setup(o => o.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(_transactionMock.Object);
            _sessionMock.Setup(o => o.Transaction.IsActive).Returns(false); 
            _unitOfWork = new UnitOfWork(_unitOfWorkFactoryMock.Object, _sessionMock.Object);
        }

        [TestMethod]
        public void DisposeUnitOfWorkImplementor()
        {
           
            _unitOfWork.Dispose();
            _unitOfWorkFactoryMock.Verify(o => o.DisposeUnitOfWork(_unitOfWork));
            _sessionMock.Verify(o => o.Dispose());
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ThrowExceptionOnBeginTransactionWhenOneIsOpend()
        {
            _sessionMock.Setup(o => o.Transaction.IsActive).Returns(true);
            _unitOfWork.BeginTransaction();
        }

        [TestMethod]
        public void ExecuteTransactionalFlush()
        {
            _unitOfWork.CommitTransaction();
            _transactionMock.Verify(o => o.Commit());
            _transactionMock.Verify(o => o.Dispose());
        }

        [TestMethod]
        public void RollbackTransactionIfExceptionWasCaught()
        {
            _unitOfWork.IsExecutionException = true;
            _unitOfWork.Dispose();
            _transactionMock.Verify(o => o.Rollback());
            _transactionMock.Verify(o => o.Dispose());
        } 
    }
}
